{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### chap8 函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在本章中，你将会学习编写**函数**。函数是带名字的代码块，用于完成具体的工作。最后将会学习到将函数存储到一个称为**模块**的独立文件中。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.1 定义函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用def定义函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello\n"
     ]
    }
   ],
   "source": [
    "def greet_user():\n",
    "    print(\"Hello\")\n",
    "    return\n",
    "\n",
    "greet_user()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用def来告诉Python解释器定义函数，括号里可以传入参数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我使用的greet_user()是调用函数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, Bedoom\n"
     ]
    }
   ],
   "source": [
    "def greet_user(username):\n",
    "    print(\"Hello, \" + username.title())\n",
    "    return\n",
    "\n",
    "greet_user('bedoom')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这个函数需要接收到你的username，例如我是把'bedoom'传入参数，从而调用函数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其中username被称为形参，你可以理解为占了一个坑位，以后找实参来填。'bedoom'是实参，它才是真正参与函数的参数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.2 传递实参"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 8.2.1 位置实参"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "根据形参的相对位置，进行对应。不需要指定形参名。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Hi, I have a hamster.\n",
      "Myhamster's name is harry\n"
     ]
    }
   ],
   "source": [
    "def describe_pet(anmial_type, pet_name):\n",
    "    \"\"\"显示宠物的信息\"\"\"\n",
    "    print(\"\\nHi, I have a \" + anmial_type + \".\")\n",
    "    print(\"My\" + anmial_type + \"'s name is \" + pet_name)\n",
    "    return\n",
    "\n",
    "describe_pet('hamster', 'harry')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Python解释器会自动识别成anmial = 'hamster', pet_name = 'harry'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 8.2.2 关键词实参"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "顾名思义，需要你提供关键词，因此你不需要过分注意顺序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Hi, I have a hamster.\n",
      "Myhamster's name is harry\n"
     ]
    }
   ],
   "source": [
    "describe_pet(pet_name='harry', anmial_type='hamster')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Hi, I have a hamster.\n",
      "Myhamster's name is harry\n"
     ]
    }
   ],
   "source": [
    "describe_pet('hamster', pet_name='harry')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 默认值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以指定形参默认值，但是注意具有默认值的形参应在没有默认值的形参后面"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def describe_pet(pet_name, anmial_type='dog'):\n",
    "    \"\"\"显示宠物的信息\"\"\"\n",
    "    print(\"\\nHi, I have a \" + anmial_type + \".\")\n",
    "    print(\"My\" + anmial_type + \"'s name is \" + pet_name)\n",
    "    return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Hi, I have a dog.\n",
      "Mydog's name is honey\n"
     ]
    }
   ],
   "source": [
    "describe_pet('honey')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当然你也可以为之改变默认值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Hi, I have a hamster.\n",
      "Myhamster's name is harry\n"
     ]
    }
   ],
   "source": [
    "describe_pet(anmial_type='hamster', pet_name='harry')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.3 返回值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "函数并非总是直接显示输出，相反，它可以处理一些数据，并返回一个或一组值。函数返回的值被称为返回值 。在函数中，可使用return 语句将值返回到调用函数的代码行。\n",
    "返回值让你能够将程序的大部分繁重工作移到函数中去完成，从而简化主程序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "John Lee Hooker\n"
     ]
    }
   ],
   "source": [
    "def get_formatted_name(first_name, middle_name, last_name):\n",
    "    \"\"\"返回整洁的姓名\"\"\"\n",
    "    full_name = first_name + ' ' + middle_name + ' ' + last_name\n",
    "    return full_name.title()\n",
    "musician = get_formatted_name('john', 'lee', 'hooker')\n",
    "print(musician)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "****"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "singer: bedoom\n",
      "album: me\n",
      "{'singer': 'bedoom', 'album': 'me'}\n",
      "0 or 1: 1\n",
      "singer: doom\n",
      "album: be\n",
      "{'singer': 'doom', 'album': 'be'}\n",
      "0 or 1: 0\n"
     ]
    }
   ],
   "source": [
    "def make_album(singer, album, songs=-1):\n",
    "    if songs == -1:\n",
    "        return {'singer': singer, 'album': album}\n",
    "    else:\n",
    "        return {'singer': singer, 'album': album, 'songs': songs}\n",
    "\n",
    "flag = 1\n",
    "while flag:\n",
    "    singer = input(\"singer: \")\n",
    "    album = input(\"album: \")\n",
    "    print(make_album(singer, album))\n",
    "    flag = int(input(\"0 or 1: \"))\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.4 修改"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "将列表传递给函数后，函数就可对其进行修改。在函数中对这个列表所做的任何修改都是**永久性**的，这让你能够高效地处理大量的数据。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "若你不想要去修改列表，可以将副本传入参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "function_name(a[:])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "a[:]是传入列表副本"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.5 传入任意个数的实参"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果你不知道有多少实参，建议使用*号"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_pizza(*topping):\n",
    "    \"\"\"披萨所需的原料\"\"\"\n",
    "    print(topping)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('a', 'b', 'c')\n"
     ]
    }
   ],
   "source": [
    "make_pizza('a', 'b', 'c')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*topping会使Python解释器创建一个空元组，并将所有值传入这个空元组"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 8.5.1 结合位置实参和任意数量实参"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Python解释器需要先确定位置实参和关键字实参，再来确定任意数量实参。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "但是有时我们不知道这些任意实参的含义，因此我们需要有解释这些实参的代码。这是\\*\\*就派上用场了"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}\n"
     ]
    }
   ],
   "source": [
    "def build_profile(first, last, **user_info):\n",
    "    \"\"\"创建一个字典，其中包含我们知道的有关用户的一切\"\"\"\n",
    "    profile = {}\n",
    "    profile['first_name'] = first\n",
    "    profile['last_name'] = last \n",
    "    for key, value in user_info.items():\n",
    "        profile[key] = value\n",
    "    return profile\n",
    "\n",
    "user_profile = build_profile('albert', 'einstein',\n",
    "                            location='princeton',\n",
    "                            field='physics')\n",
    "print(user_profile)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "它会创建一个空字典，并将key和value封装到这个字典中"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.6 将函数存储到模块中"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "函数的优点之一是，使用它们可将代码块与主程序分离。通过给函数指定描述性名称，可让主程序容易理解得多。你还可以更进一步，将函数存储在被称为**模块**的独立文件中，再将模块导入 到主程序中。<br></br>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "import 语句允许在当前运行的程序文件中使用模块中的代码。<br></br>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过将函数存储在独立的文件中，可隐藏程序代码的细节，将重点放在程序的高层逻辑上。这还能让你在众多不同的程序中重用函数。<br></br>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "将函数存储在独立文件中后，可与其他程序员共享这些文件而不是整个程序。知道如何导入函数还能让你使用其他程序员编写的函数库。<br></br>\n",
    "导入模块的方法有多种，下面对每种都作简要的介绍。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 8.6.1 导入整个模块 "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "import导入"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Making a16-inch pizza with the following toppings:\n",
      "- pepperoni\n"
     ]
    }
   ],
   "source": [
    "import pizza\n",
    "pizza.make_pizza(16, 'pepperoni')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 8.6.2 导入特定模块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Making a16-inch pizza with the following toppings:\n",
      "- pepperoni\n",
      "\n",
      "Making a12-inch pizza with the following toppings:\n",
      "- mushrooms\n",
      "- green peppers\n",
      "- extra cheese\n"
     ]
    }
   ],
   "source": [
    "from pizza import make_pizza\n",
    "make_pizza(16, 'pepperoni')\n",
    "make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "from ... import ..."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 使用as加别名"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Making a16-inch pizza with the following toppings:\n",
      "- pepperoni\n"
     ]
    }
   ],
   "source": [
    "from pizza import make_pizza as making\n",
    "making(16, 'pepperoni')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.8 小结"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在本章中，你学习了：\n",
    "1. 如何编写函数，以及如何传递实参，让函数能够访问完成其工作所需的信息；\n",
    "2. 如何使用位置实参和关键字实参，以及如何接受任意数量的实参；\n",
    "3. 显示输出的函数和返回值的函数；\n",
    "4. 如何将函数同列表、字典、if 语句和while 循环结合起来使用。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "你还知道了如何将函数存储在被称为模块 的独立文件中，让程序文件更简单、更易于理解。最后，你学习了函数编写指南，遵循这些指南可让程序始终结构良好，并对你和其他人来说易于阅读。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "程序员的目标之一是，编写简单的代码来完成任务，而函数有助于你实现这样的目标。它们让你编写好代码块并确定其能够正确运行后，就可置之不理。确定函数能够正确地完成其工作后，你就可以接着投身于下一个编码任务。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
